module DataPath(
	input clk,
	input rst,
	input [31:0] inst_field,
	input [31:0] Data_in,
	input [2:0] ALU_operation,
	input [1:0] ImmSel,
	input [1:0] MemtoReg,
	input ALUSrc_B,
	input Jump,
	input Branch,
	input RegWrite,
	output [31:0] ALU_out,
	output [31:0] Data_out,
	output [31:0] PC_out,
	 output [31:0] x0,
    output [31:0] ra,
    output [31:0] sp,
    output [31:0] gp,
    output [31:0] tp,
    output [31:0] t0,
    output [31:0] t1,
    output [31:0] t2,
    output [31:0] s0,
    output [31:0] s1,
    output [31:0] a0,
    output [31:0] a1,
    output [31:0] a2,
    output [31:0] a3,
    output [31:0] a4,
    output [31:0] a5,
    output [31:0] a6,
    output [31:0] a7,
    output [31:0] s2,
    output [31:0] s3,
    output [31:0] s4,
    output [31:0] s5,
    output [31:0] s6,
    output [31:0] s7,
    output [31:0] s8,
    output [31:0] s9,
    output [31:0] s10,
    output [31:0] s11,
    output [31:0] t3,
    output [31:0] t4,
    output [31:0] t5,
    output [31:0] t6
    );
    
    wire [31:0] Wt_data, Rs1_data, Rs2_data, D, Q;
    wire [31:0] Imm_out, PC_1, PC_2, MUX2T1_32_1_o;
    wire [31:0] B, res;
    wire sel, zero;
    
    assign sel=Branch&zero;
    assign Data_out=Rs2_data;
    assign PC_out=Q;
    assign ALU_out=res;
    
    REGs Regs(
    .clk(clk),
    .rst(rst),
    .Rs1_addr(inst_field[19:15]),
    .Rs2_addr(inst_field[24:20]),
    .Wt_addr(inst_field[11:7]),
    .Wt_data(Wt_data),
    .RegWrite(RegWrite),
    .Rs1_data(Rs1_data),
    .Rs2_data(Rs2_data),
	.x0(x0),
    .ra(ra),
    .sp(sp),
    .gp(gp),
    .tp(tp),
    .t0(t0),
    .t1(t1),
    .t2(t2),
    .s0(s0),
    .s1(s1),
    .a0(a0),
    .a1(a1),
    .a2(a2),
    .a3(a3),
    .a4(a4),
    .a5(a5),
    .a6(a6),
    .a7(a7),
    .s2(s2),
    .s3(s3),
    .s4(s4),
    .s5(s5),
    .s6(s6),
    .s7(s7),
    .s8(s8),
    .s9(s9),
    .s10(s10),
    .s11(s11),
    .t3(t3),
    .t4(t4),
    .t5(t5),
    .t6(t6)    
    );
        
    REG32 PC(
    .clk(clk),
    .rst(rst),
    .CE(1'b1),
    .D(D),
    .Q(Q)
    );
    
    add_32_0 add_32_0 (
	.a(Q),  // input wire [31 : 0] a
	.b(32'd4),  // input wire [31 : 0] b
	.c(PC_1)  // output wire [31 : 0] c
	);
	
	add_32_0 add_32_1 (
	.a(Q),  // input wire [31 : 0] a
	.b(Imm_out),  // input wire [31 : 0] b
	.c(PC_2)  // output wire [31 : 0] c
	);
	
	MUX2T1_32_0 MUX2T1_32_1 (
	.I0(PC_1),  // input wire [31 : 0] I0
	.I1(PC_2),  // input wire [31 : 0] I1
	.s(sel),    // input wire s
	.o(MUX2T1_32_1_o)    // output wire [31 : 0] o
	);
	
	MUX2T1_32_0 MUX2T1_32_3 (
	.I0(MUX2T1_32_1_o),  // input wire [31 : 0] I0
	.I1(PC_2),  // input wire [31 : 0] I1
	.s(Jump),    // input wire s
	.o(D)    // output wire [31 : 0] o
	);
	
	MUX2T1_32_0 MUX2T1_32_0 (
	.I0(Rs2_data),  // input wire [31 : 0] I0
	.I1(Imm_out),  // input wire [31 : 0] I1
	.s(ALUSrc_B),    // input wire s
	.o(B)    // output wire [31 : 0] o
	);
	
	ImmGen ImmGen(
	.ImmSel(ImmSel),
	.inst_field(inst_field),
	.Imm_out(Imm_out)
	);
    
    ALU_0 ALU (
    .A(Rs1_data),                          // input wire [31 : 0] A
    .B(B),                          // input wire [31 : 0] B
    .ALU_operation(ALU_operation),  // input wire [2 : 0] ALU_operation
    .res(res),                      // output wire [31 : 0] res
    .zero(zero)                    // output wire zero
	);
	
	MUX4T1_32_0 MUX4T1_32_0 (
    .I0(res),  // input wire [31 : 0] I0
    .I1(Data_in),  // input wire [31 : 0] I1
    .I2(PC_1),  // input wire [31 : 0] I2
    .I3(PC_1),  // input wire [31 : 0] I3
    .s(MemtoReg),    // input wire [1 : 0] s
    .o(Wt_data)    // output wire [31 : 0] o
    );
	
endmodule